/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:        sqbang                                                 *
 * Email:         sqbang@ustc.edu                                        *
 * Date:          2012.01.12                                             *
 *                                                                       *
 *************************************************************************/

//declaration header
#include "COMMON/syst/SystemStrategy.h"

//COMMON headers
#include "COMMON/equa/PDEEquationEnsembleStrategy.h"
#include "COMMON/equa/EquationDomain.h"
#include "COMMON/info/InfoManager.h"
#include "COMMON/info/CommonInfo.h"
#include "COMMON/regn/Region.h"
#include "COMMON/tbox/LogMessage.h"

namespace FreeMAPs
{

SystemStrategy::SystemStrategy (
    const std::string& parent_name,
    const std::string& object_name,
    PDEEquationEnsembleStrategy& equation_ensemble):
    StateIndicator (parent_name, object_name, false),
    d_equation_ensemble (equation_ensemble),
    d_system_type("IMPLICIT"),
    d_solver_method("LINEAR")
{
}



SystemStrategy::~SystemStrategy()
{
    this->clear();
}



const std::string
SystemStrategy::get_system_type() const
{
    return d_system_type;
}



void
SystemStrategy::set_system_type(
        const std::string& system_type)
{
    d_system_type = system_type;
}



const std::string
SystemStrategy::get_solver_method() const
{
    return d_solver_method;
}



void
SystemStrategy::set_solver_method(
        const std::string& solver_method)
{
    d_solver_method = solver_method;
}



void
SystemStrategy::clear()
{}



void
SystemStrategy::get_from_input (
    const InputDatabase* db)
{
    this->prepare_for_use (db);

    db->insert_allowable_key ("type");
    db->insert_allowable_key ("solver");

    db->check_allowable_keys ();

    /*
     * type
     */
    if( db->key_exists("type") && db->is_string("type") )
    {
        d_system_type = db->get_string("type");
    }


    /*
     * solver method
     */
    if(db->key_exists("solver") && db->is_database("solver"))
    {
        db->check_requisite_key ("solver", DataType::DATABASE, false, false);

        const InputDatabase* solver_db = db->get_database ("solver");

        if( solver_db->key_exists("method") && solver_db->is_string("method") )
        {
            d_solver_method = solver_db->get_string("method");
        }
    }
}



std::ostream&
operator << (
    std::ostream& os,
    const SystemStrategy& rhs)
{
    os << "system\n{\n";

    std::ostringstream oss;

    if( rhs.get_system_type() == "EXPLICIT" )
    {
        // TODO
    }
    else if( rhs.get_system_type() == "IMPLICIT" )
    {
        oss << "type = \"IMPLICIT\"" << "\n\n";
        oss << "solver"<< "\n";
        oss << "{"<< "\n";
        oss << LogMessage::get_prefix (ONE_TAB) << "method = \"" << rhs.get_solver_method() << "\"" << "\n";
        oss << "}" << "\n";
    }

    os << LogMessage::get_log_info (oss, ONE_TAB) << "\n";

    os << "}";

    return os;
}

}
